package com.ding.easycontroller.filter;

import com.ding.easycontroller.service.ControllerService;
import com.ding.easycontroller.service.FilterService;
import com.ding.easycontroller.utils.ParamUtils;
import com.ding.easycontroller.work.Controller;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.filter.OrderedFilter;
import org.springframework.stereotype.Component;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

@Component
public class HandlerFilter implements OrderedFilter {

    @Autowired
    private ControllerService controllerService;

    @Autowired
    private FilterService filterService;

    @Autowired
    private ParamUtils paramUtils;


    private List<String> openPres = new ArrayList<>();
    private List<String> openUris = new ArrayList<>();

    public HandlerFilter(@Value("${websocket.basePath:/socket/}") String base) {
        openPres.add(base);
        openPres.add("/_config/");
        openPres.add("/_console/");

        openUris.add("/favicon.ico");
        openUris.add("/_console");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        doHandle(servletRequest, servletResponse, filterChain);
    }

    private void doHandle(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String uri = request.getRequestURI();

        for (String s : openUris) {
            if (uri.equals(s)) {
                filterChain.doFilter(request, servletResponse);
                return;
            }
        }
        for (String openPre : openPres) {
            if (uri.startsWith(openPre)) {
                filterChain.doFilter(request, servletResponse);
                return;
            }
        }

        String method = request.getMethod().toUpperCase();
        Controller controller = controllerService.matchesController(uri, method);
        if (controller == null) {
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            response.setContentType("Content-Type: text/html;charset=UTF-8");
            List<com.ding.easycontroller.work.Filter> defaultFilters = filterService.getDefaultFilters();
            if (defaultFilters.size() > 0) {
                Object[] filterParams = paramUtils.params(request, (HttpServletResponse) servletResponse);
                Writer writer = (Writer) filterParams[4];
                for (com.ding.easycontroller.work.Filter d : defaultFilters) {
                    com.ding.easycontroller.work.Filter.Result result = d.doDefaultFilter(filterParams);
                    if (result.getStatus() != null) {
                        ((HttpServletResponse) servletResponse).setStatus(result.getStatus());
                    }

                    if (!result.isGoOn()) {
                        writer.flush();
                        return;
                    }
                }
                writer.flush();
            }

            filterChain.doFilter(servletRequest, servletResponse);
        } else {

            HttpServletResponse response = (HttpServletResponse) servletResponse;


            Object[] filterParams = paramUtils.params(request, response);

            response.setContentType("Content-Type: text/html;charset=UTF-8");

            Writer writer = (Writer) filterParams[4];

            //遍历前置拦截器
            List<com.ding.easycontroller.work.Filter> beforeFilters = filterService.getBeforeFilters();
            for (com.ding.easycontroller.work.Filter beforeFilter : beforeFilters) {

                com.ding.easycontroller.work.Filter.Result result = beforeFilter.doBeforeFilter(filterParams);

                if (result.getStatus() != null) {
                    ((HttpServletResponse) servletResponse).setStatus(result.getStatus());
                }

                if (!result.isGoOn()) {
                    writer.flush();
                    return;
                }

            }


            //先准备参数
            Object[] params = controller.prepare(filterParams);

            //处理请求
            Controller.Result result = controller.handle(params);

            if (result.getStatus() != null) {
                response.setStatus(result.getStatus());
            }

            //遍历后置拦截器
            List<com.ding.easycontroller.work.Filter> afterFilters = filterService.getAfterFilters();
            for (com.ding.easycontroller.work.Filter filter : afterFilters) {
                com.ding.easycontroller.work.Filter.Result r = filter.doAfterFilter(filterParams);

                if (r.getStatus() != null) {
                    ((HttpServletResponse) servletResponse).setStatus(r.getStatus());
                }

                if (!r.isGoOn()) {
                    writer.flush();
                    return;
                }
            }


            //将最终处理结果进行写入
            //遍历响应头,将响应头写入响应中
            ScriptObjectMirror respHeads = (ScriptObjectMirror) filterParams[10];
            for (String s : respHeads.keySet()) {
                response.setHeader(s, respHeads.get(s).toString());
            }

            if (result.getData() != null) {
                writer.write(result.getData());

            }

            writer.flush();
        }
    }


    @Override
    public int getOrder() {
        return Integer.MIN_VALUE + 1;
    }
}
